#include "qtranslatetreewidget.h"

#include "qbtnlineedit.h"

#include "../../libs/sharedLib/qlanguagemanager.h"
#include "../../libs/sharedLib/qprojectcore.h"
#include "../../libs/coreLib/qsoftcore.h"
#include "../../libs/coreLib/qundocommand/qabstractundocommand.h"
#include "../../libs/coreLib/qundocommand/qcommandobject.h"

#include <QHeaderView>
#include <QPainter>
#include <QApplication>
#include <QMouseEvent>
#include <QHBoxLayout>
#include <QLineEdit>

static QIcon drawIndicatorIcon(const QPalette &palette,QStyle *style)
{
    QPixmap pix(14,14);

    pix.fill(Qt::transparent);

    QStyleOption branchOption;
    QRect r(QPoint(0,0),pix.size());
    branchOption.rect=QRect(2,2,9,9);
    branchOption.palette=palette;
    branchOption.state=QStyle::State_Children;

    QPainter p;
    p.begin(&pix);
    style->drawPrimitive(QStyle::PE_IndicatorBranch,&branchOption,&p);
    p.end();
    QIcon rc=pix;
    rc.addPixmap(pix,QIcon::Selected,QIcon::Off);
    branchOption.state |=QStyle::State_Open;

    pix.fill(Qt::transparent);
    p.begin(&pix);
    style->drawPrimitive(QStyle::PE_IndicatorBranch,&branchOption,&p);
    p.end();

    rc.addPixmap(pix,QIcon::Normal,QIcon::On);
    rc.addPixmap(pix,QIcon::Selected,QIcon::On);
    return rc;
}

QWidget *QTranslateDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &/*option*/, const QModelIndex &index) const
{
    QWidget *ret=NULL;
    if(index.column()>0)
    {
        QBtnLineEdit *e=new QBtnLineEdit(parent);
        ret=e;
    }
    if(ret!=NULL)
    {
        ret->setProperty("no-ManhattanStyle",true);
    }
    return ret;
}

void QTranslateDelegate::updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &/*index*/) const
{
    editor->setGeometry(option.rect.adjusted(0,0,0,-1));
}

QSize QTranslateDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const
{
    QSize size=QItemDelegate::sizeHint(option,index);
    size.setHeight(22);
    size.rwidth()+=4;
    return size;
}

void QTranslateDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
    QTreeWidgetItem* item=m_listView->indexToItem(index);
    QStyleOptionViewItemV3 opt=option;
    QColor c;
    if(item!=NULL)
    {
        if(m_listView->isGroupItem(item))
        {
            c=opt.palette.color(QPalette::Dark);
            opt.palette.setColor(QPalette::Text,opt.palette.color(QPalette::BrightText));
        }
        else
        {
            QModelIndex temp=index;
            while(temp.isValid() && !m_listView->isGroupItem(m_listView->indexToItem(temp)))
            {
                temp=temp.parent();
            }
            if(temp.isValid())
            {
                QTreeWidgetItem *tempItem=m_listView->indexToItem(temp);
                c=m_listView->m_colors.at(m_listView->m_groups.indexOf(tempItem)%m_listView->m_colors.count()).first;
            }
            else
            {
                c=m_listView->m_colors.at(0).first;
            }
            if(opt.features & QStyleOptionViewItemV2::Alternate)
            {
                c=c.lighter(112);
            }
            SHAREDLIB::QLanguageManager *la=SHAREDLIB::QProjectCore::getCore()->languageManager();
            if(la->getCurrentLanguage()->property("languageName").toString()==m_listView->headerItem()->text(index.column()))
            {
                c=QColor(220,220,220);
            }
        }
    }



    painter->fillRect(option.rect,c);
    opt.state &=~ QStyle::State_HasFocus;
    QItemDelegate::paint(painter,opt,index);
    opt.palette.setCurrentColorGroup(QPalette::Active);
    QColor color=static_cast<QRgb>(qApp->style()->styleHint(QStyle::SH_Table_GridLineColor,&opt));
    painter->setPen(color);

    if(!m_listView->isGroupItem(item))
    {
        if(index.column()!=m_listView->columnCount()-1)
        {
            int right=option.direction==Qt::LeftToRight?option.rect.right():option.rect.left();
            painter->drawLine(right,option.rect.y(),right,option.rect.bottom());
        }
    }
}

void QTranslateDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const
{
    QLineEdit* edit=(QLineEdit*) editor;
    model->setData(index,edit->text(),Qt::UserRole);
    QString str=edit->text().replace("\r\n"," ");
    str=str.replace("\n"," ");
    model->setData(index,str,Qt::EditRole);
    QTreeWidgetItem *item=m_listView->indexToItem(index);
    SHAREDLIB::QLanguageManager *la=SHAREDLIB::QProjectCore::getCore()->languageManager();
    str=item->parent()->text(0)+"."+item->text(0);
    QString name=m_listView->headerItem()->text(index.column());
    QString id=str;
    QString text=index.data(Qt::UserRole).toString();
    if(la->getText(name,id)!=text)
    {
        QMap<QString,QVariant> param;
        param.insert("id",id);
        param.insert("new_text",text);
        param.insert("old_text",la->getText(name,id));
        param.insert("index",index.column());

        CORELIB::QAbstractUndoCommand* cmd=new CORELIB::QAbstractUndoCommand(param);
        connect(cmd->object(),SIGNAL(redo()),m_listView,SLOT(cammand_changed()));
        connect(cmd->object(),SIGNAL(undo()),m_listView,SLOT(cammand_changed()));
        CORELIB::QSoftCore::getCore()->get_undo_stack()->push(cmd);
    }
}

void QTranslateDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const
{
    QLineEdit* edit=(QLineEdit*) editor;
    edit->setText(index.data(Qt::UserRole).toString());
}

QTranslateTreeWidget::QTranslateTreeWidget(QWidget *parent):
    QTreeWidget(parent)
{
    QVector<QColor> colors;
    colors.reserve(6);
    colors.push_back(QColor(255,230,191));
    colors.push_back(QColor(255,255,191));
    colors.push_back(QColor(191,255,191));
    colors.push_back(QColor(199,255,255));
    colors.push_back(QColor(234,191,255));
    colors.push_back(QColor(255,191,239));
    m_colors.reserve(colors.count());
    const int darknessFactor=250;
    for(int i=0;i<colors.count();i++)
    {
        QColor c=colors.at(i);
        m_colors.push_back(qMakePair(c,c.darker(darknessFactor)));
    }

    this->setItemDelegate(new QTranslateDelegate(this));

    SHAREDLIB::QLanguageManager *la=SHAREDLIB::QProjectCore::getCore()->languageManager();
    connect(la,SIGNAL(refresh()),this,SLOT(refresh()));
    connect(la,SIGNAL(itemChanged(SHAREDLIB::tagLanguageItem*)),this,SLOT(translateChanged(SHAREDLIB::tagLanguageItem*)));
    connect(la,SIGNAL(removeItem(QString)),this,SLOT(removeTranslate(QString)));

    connect(this,SIGNAL(clicked(QModelIndex)),this,SLOT(edit(QModelIndex)));


    m_expandIcon=drawIndicatorIcon(this->palette(),this->style());
}

QTreeWidgetItem *QTranslateTreeWidget::indexToItem(const QModelIndex &index) const
{
    return itemFromIndex(index);
}

bool QTranslateTreeWidget::isGroupItem(QTreeWidgetItem *item)const
{
    return m_groups.contains(item);
}

void QTranslateTreeWidget::addTranslateItem(SHAREDLIB::tagLanguageItem *translate)
{
    if(translate==NULL || m_items.keys().contains(translate))
    {
        return;
    }
    QString id1=translate->m_id;
    QString id2;
    int index=id1.indexOf(".");
    if(index<=0)
    {
        return;
    }

    id2=id1.mid(index+1);
    id1=id1.left(index);

    QTreeWidgetItem *parent=m_nameToGroup.value(id1);
    if(parent==NULL)
    {
        parent=new QTreeWidgetItem(this);
        parent->setText(0,id1);
        parent->setIcon(0,m_expandIcon);
        parent->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled);
        m_groups.append(parent);
        m_nameToGroup.insert(id1,parent);
        this->expandItem(parent);
    }
    QTreeWidgetItem *item=new QTreeWidgetItem(parent);
    item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsEditable);
    m_items.insert(translate,item);
    item->setText(0,id2);

    QMapIterator<QObject*,int> it(m_languageIndex);
    QString str;
    while(it.hasNext())
    {
        it.next();
        str=translate->m_translate.value(it.key(),"");
        item->setData(it.value(),Qt::UserRole,str);
        item->setToolTip(it.value(),str);
        str=str.replace("\r\n"," ");
        str=str.replace("\n"," ");
        item->setText(it.value(),str);
    }
}

void QTranslateTreeWidget::refresh()
{
    clearAll();

    QStringList list;
    list<<"ID";

    SHAREDLIB::QLanguageManager *la=SHAREDLIB::QProjectCore::getCore()->languageManager();
    int count=la->languageCount();

    for(int i=0;i<count;i++)
    {
        QObject *obj=la->getLanguage(i);
        list.append(obj->property("languageName").toString());
        m_languageIndex.insert(obj,i+1);
    }

    this->setColumnCount(0);
    setHeaderLabels(list);

    count=la->getItemCount();
    for(int i=0;i<count;i++)
    {
        addTranslateItem(la->getTextItem(i));
    }
    this->expandAll();
}

void QTranslateTreeWidget::clearAll()
{
    this->clear();
    m_groups.clear();
    m_nameToGroup.clear();
    m_items.clear();
    m_languageIndex.clear();
    this->setColumnCount(0);
    this->setHeaderLabels(QStringList()<<"ID");
}

void QTranslateTreeWidget::translateChanged(SHAREDLIB::tagLanguageItem *item)
{
    QTreeWidgetItem* temp=NULL;
    QMapIterator<SHAREDLIB::tagLanguageItem*,QTreeWidgetItem*> it(m_items);
    while(it.hasNext())
    {
        it.next();
        if(it.key()->m_id==item->m_id)
        {
            temp=it.value();
            break;
        }
    }
    if(temp==NULL)
    {
        addTranslateItem(item);
    }
    else
    {
        QMapIterator<QObject*,int> it(m_languageIndex);
        while(it.hasNext())
        {
            it.next();
            QString str=item->m_translate.value(it.key(),"");
            temp->setToolTip(it.value(),str);
            temp->setData(it.value(),Qt::UserRole,str);
            str=str.replace("\r\n"," ");
            str=str.replace("\n"," ");
            temp->setText(it.value(),str);
        }
    }
}

void QTranslateTreeWidget::removeTranslate(const QString &id)
{
    QString id1=id;
    QString id2;
    int index=id1.indexOf(".");
    if(index<=0)
    {
        return;
    }
    id2=id1.mid(index+1);
    id1=id1.left(index);
    QMapIterator<SHAREDLIB::tagLanguageItem*,QTreeWidgetItem*>  it(m_items);
    while(it.hasNext())
    {
        it.next();
        if(it.key()->m_id==id)
        {
            delete it.value();
            m_items.remove(it.key());
            break;
        }
    }
    QTreeWidgetItem *p=m_nameToGroup.value(id1);
    if(p!=NULL)
    {
        if(p->childCount()==0)
        {
            m_nameToGroup.remove(id1);
            m_groups.removeAll(p);
            delete p;
        }
    }
}

void QTranslateTreeWidget::mousePressEvent(QMouseEvent *event)
{
    QTreeWidget::mousePressEvent(event);

    QTreeWidgetItem *item=itemAt(event->pos());

    if(item)
    {
        if(m_groups.contains(item))
        {
            if(event->pos().x()+header()->offset()<20)
            {
                item->setExpanded(!item->isExpanded());
            }
        }
    }
}

void QTranslateTreeWidget::drawRow(QPainter *painter, const QStyleOptionViewItem &options, const QModelIndex &index) const
{
    QModelIndex temp=index;
    while(temp.isValid() && !isGroupItem(indexToItem(temp)))
    {
        temp=temp.parent();
    }
    QTreeWidgetItem* item=indexToItem(index);
    QTreeWidgetItem* tempItem=indexToItem(temp);
    QStyleOptionViewItemV3 opt=options;
    QColor c;
    if(item!=NULL)
    {
        if(!m_groups.contains(item))
        {
            c=m_colors.at(m_groups.indexOf(tempItem)%m_colors.count()).first;
            painter->fillRect(options.rect,c);
            opt.palette.setColor(QPalette::AlternateBase,c.lighter(112));
        }
        else
        {
            c=opt.palette.color(QPalette::Dark);
            painter->fillRect(options.rect,c);
            opt.palette.setColor(QPalette::AlternateBase,c);
        }
    }


    QTreeWidget::drawRow(painter,opt,index);

    QColor color=static_cast<QRgb>(QApplication::style()->styleHint(QStyle::SH_Table_GridLineColor));
    painter->setPen(color);
    painter->drawLine(opt.rect.x(),opt.rect.bottom(),opt.rect.right(),opt.rect.bottom());
}

void QTranslateTreeWidget::removeCurrent()
{
    QMapIterator<SHAREDLIB::tagLanguageItem*,QTreeWidgetItem*>  it(m_items);
    while(it.hasNext())
    {
        it.next();
        if(it.value()->isSelected())
        {
            QTreeWidgetItem *item=it.value();
            QString str;
            str=item->parent()->text(0)+"."+item->text(0);
            SHAREDLIB::QProjectCore::getCore()->languageManager()->removeTextItem(str);
            return;
        }
    }
}

void QTranslateTreeWidget::updateAll()
{
    this->collapseAll();
    this->expandAll();
}

void QTranslateTreeWidget::cammand_changed()
{
    SHAREDLIB::QLanguageManager *la=SHAREDLIB::QProjectCore::getCore()->languageManager();
    QString id=sender()->property("id").toString();
    QString old_text=sender()->property("old_text").toString();
    QString new_text=sender()->property("new_text").toString();
    int index=sender()->property("index").toInt();
    QObject* obj=la->getLanguage(index-1);

    la->setText(obj->property("languageName").toString(),id,new_text);

    SHAREDLIB::tagLanguageItem *item=la->getTextItem(id);
    if(item!=NULL)
    {
        QTreeWidgetItem *it=m_items.value(item);
        QString str=new_text.replace("\r\n","");
        str=str.replace("\n"," ");
        it->setText(index,str);
        it->setToolTip(index,new_text);
        it->setData(index,Qt::UserRole,new_text);
    }

    sender()->setProperty("old_text",new_text);
    sender()->setProperty("new_text",old_text);
}

void QTranslateTreeWidget::cammand_add()
{

}

void QTranslateTreeWidget::cammand_remove()
{

}
